#include "calc.h"
#include "calcgui.h"
#include "button.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QRadioButton>
#include <QMenu>
#include <QMenuBar>
#include <QAction>
#include <QGroupBox>
#include <QMessageBox>

// Construtor. Inicializa a interface gráfica da calculadora em modo simples
CalcGui::CalcGui() :
    QMainWindow()
{
    // Inicializa a calculadora em modo simples
    cientific = false;

    // Variáveis auxiliares
    Button *b;
    QRadioButton *rb;
    QMenu *menu;
    QAction *menuItem;

    // Cria um QSignalMapper para mapear os botões
    signalMapper = new QSignalMapper(this);

    // Cria um widget central para conter o Layout principal
    QWidget *mainWidget = new QWidget();
    QVBoxLayout *mainLayout = new QVBoxLayout;
    mainWidget->setLayout(mainLayout);
    setCentralWidget(mainWidget);

    // Adiciona a barra de menu
    menuShow = menuBar()->addMenu("&Show");
    QVBoxLayout *mode = new QVBoxLayout();                       // Foi criado um QVBoxLayout ao invés de adicionar
    rb = new QRadioButton(QString(tr("Simple")));                // QActions para pudessem ser utilizados QRadioButtons
    rb->setChecked(true);                                        // na seleção do modo, um vez que estes são mutuamente exclusivos.
    connect(rb, SIGNAL(clicked()), this, SLOT(changeToSimple()));
    mode->addWidget(rb);
    rb = new QRadioButton(QString(tr("Cientific")));
    connect(rb, SIGNAL(clicked()), this, SLOT(changeToCientific()));
    mode->addWidget(rb);
    menuShow->setLayout(mode);

    menu = menuBar()->addMenu("&Help");
    menuItem = new QAction(QString(tr("About")), menu);
    connect(menuItem, SIGNAL(triggered()), this, SLOT(about()));
    menu->addAction(menuItem);

    // Adiciona componentes ao layout principal
    display = new QLineEdit(); // Este é o display da calculadora
    display->setReadOnly(true);
    display->setAlignment(Qt::AlignRight);
    display->setText(QString ("0"));
    mainLayout->addWidget(display);

    keysLayout = new QHBoxLayout; // Esse layout contém o layout de modo simple e científico
    keysLayout->SetFixedSize;
    mainLayout->addLayout(keysLayout);

    widgetList.begin();
    cientificLayout = new QVBoxLayout;
    keysLayout->addLayout(cientificLayout);
    cientificLayout->setAlignment(Qt::AlignBottom);

    /*
    ########################################################################
      Inicia a intanciação de bottões do modo simples
    ########################################################################
    */
    QVBoxLayout *simpleLayout = new QVBoxLayout;
    keysLayout->addLayout(simpleLayout);

    // MC, MR, MS, M+ and M-
    QHBoxLayout *mLayout = new QHBoxLayout;
    simpleLayout->addLayout(mLayout);

    b = new Button(QString("MC"), signalMapper);
    mLayout->addWidget(b);
    b = new Button(QString("MR"), signalMapper);
    mLayout->addWidget(b);
    b = new Button(QString("MS"), signalMapper);
    mLayout->addWidget(b);
    b = new Button(QString("M+"), signalMapper);
    mLayout->addWidget(b);
    b = new Button(QString("M-"), signalMapper);
    mLayout->addWidget(b);

    // <-, CE, C, +- and sqrt
    QHBoxLayout *cLayout = new QHBoxLayout;
    simpleLayout->addLayout(cLayout);

    b = new Button(QString("<-"), signalMapper);
    cLayout->addWidget(b);
    b = new Button(QString("CE"), signalMapper);
    cLayout->addWidget(b);
    b = new Button(QString("C"), signalMapper);
    cLayout->addWidget(b);
    b = new Button(QString("+-"), signalMapper);
    cLayout->addWidget(b);
    b = new Button(QString("sqrt"), signalMapper);
    cLayout->addWidget(b);

    QHBoxLayout *subSimpleLayout = new QHBoxLayout;
    simpleLayout->addLayout(subSimpleLayout);

    QVBoxLayout *digitsLayout = new QVBoxLayout;
    subSimpleLayout->addLayout(digitsLayout);

    QHBoxLayout *sevenLine = new QHBoxLayout;
    QHBoxLayout *fourLine = new QHBoxLayout;
    QHBoxLayout *oneLine = new QHBoxLayout;
    QHBoxLayout *zeroLine = new QHBoxLayout;
    digitsLayout->addLayout(sevenLine);
    digitsLayout->addLayout(fourLine);
    digitsLayout->addLayout(oneLine);
    digitsLayout->addLayout(zeroLine);

    // 0 and ,
    b = new Button(QString("0"), signalMapper);
    zeroLine->addWidget(b,1);
    b = new Button(QString(","), signalMapper);
    zeroLine->addWidget(b);

    // 1, 2 and 3
    b = new Button(QString("1"), signalMapper);
    oneLine->addWidget(b);
    b = new Button(QString("2"), signalMapper);
    oneLine->addWidget(b);
    b = new Button(QString("3"), signalMapper);
    oneLine->addWidget(b);

    // 4, 5 and 6
    b = new Button(QString("4"), signalMapper);
    fourLine->addWidget(b);
    b = new Button(QString("5"), signalMapper);
    fourLine->addWidget(b);
    b = new Button(QString("6"), signalMapper);
    fourLine->addWidget(b);

    // 7, 8 and 9
    b = new Button(QString("7"), signalMapper);
    sevenLine->addWidget(b);
    b = new Button(QString("8"), signalMapper);
    sevenLine->addWidget(b);
    b = new Button(QString("9"), signalMapper);
    sevenLine->addWidget(b);

    QHBoxLayout *operatorsLayout = new QHBoxLayout;
    subSimpleLayout->addLayout(operatorsLayout);

    // /, *, -, +
    QVBoxLayout *plusRow = new QVBoxLayout;
    operatorsLayout->addLayout(plusRow);

    b = new Button(QString("/"), signalMapper);
    plusRow->addWidget(b);
    b = new Button(QString("*"), signalMapper);
    plusRow->addWidget(b);
    b = new Button(QString("-"), signalMapper);
    plusRow->addWidget(b);
    b = new Button(QString("+"), signalMapper);
    plusRow->addWidget(b);

    // %, 1/x, =
    QVBoxLayout *percentRow = new QVBoxLayout;
    operatorsLayout->addLayout(percentRow);

    b = new Button(QString("%"), signalMapper);
    percentRow->addWidget(b);
    b = new Button(QString("1/x"), signalMapper);
    percentRow->addWidget(b);
    b = new Button(QString("="), signalMapper);
    b->resize(b->sizeHint().rwidth(),b->sizeHint().rwidth()*2);
    percentRow->addWidget(b);

    /*
    ########################################################################
      Finaliza a instancição  dos botões de modo simples
    ########################################################################
    */

    connect(signalMapper, SIGNAL(mapped(const QString &)),
            this, SLOT(execute(const QString &)));    

    setWindowTitle(tr("Calculator"));

    setMinimumWidth(sizeHint().rwidth()/2);
    setMaximumWidth(sizeHint().rwidth()/2);
    setMinimumWidth(sizeHint().rwidth()/2);
    setMaximumWidth(sizeHint().rwidth()/2);

}

// Slot que recebe os sinais de clique nos botões e dipara ações da calculadora
void CalcGui::execute(const QString &s) {
    QString retValue("");
    Calc::clicked(s,retValue);
    display->setText(retValue);
}

// Método que é chamado para construir botões específicos para a calculadora científica
void CalcGui::changeToCientific() {
    menuShow->hide();
    /*
    ########################################################################
      Inicia a instanciação dos botões da calculadora científica
    ########################################################################
    */

    if (!cientific) {

        cientific = true;

        // Variáveis auxiliares
        Button *b;
        QRadioButton *rb;

        // Graus, radianos e grados
        QHBoxLayout *degreesLine = new QHBoxLayout;
        cientificLayout->addLayout(degreesLine);

        rb = new QRadioButton(QString(tr("Deegrees")));
        rb->setChecked(true);
        degreesLine->addWidget(rb);
        widgetList.append(rb);
        rb = new QRadioButton(QString(tr("Radians")));
        degreesLine->addWidget(rb);
        widgetList.append(rb);
        rb = new QRadioButton(QString(tr("Grads")));
        degreesLine->addWidget(rb);
        widgetList.append(rb);

        // "", Inv, ln, ( and )
        QHBoxLayout *nLine = new QHBoxLayout;
        cientificLayout->addLayout(nLine);

        b = new Button(QString(""), signalMapper);
        b->setEnabled(false);
        nLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("Inv"), signalMapper);
        nLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("ln"), signalMapper);
        nLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("("), signalMapper);
        nLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString(")"), signalMapper);
        nLine->addWidget(b);
        widgetList.append(b);

        // Int, sinh, sin, x^2 and n!
        QHBoxLayout *intLine = new QHBoxLayout;
        cientificLayout->addLayout(intLine);

        b = new Button(QString("Int"), signalMapper);
        intLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("sinh"), signalMapper);
        intLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("sin"), signalMapper);
        intLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("x^2"), signalMapper);
        intLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("n!"), signalMapper);
        intLine->addWidget(b);
        widgetList.append(b);

        // dms, cosh, cos, x^y and x^1/y
        QHBoxLayout *dmsLine = new QHBoxLayout;
        cientificLayout->addLayout(dmsLine);

        b = new Button(QString("dms"), signalMapper);
        dmsLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("cosh"), signalMapper);
        dmsLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("cos"), signalMapper);
        dmsLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("x^y"), signalMapper);
        dmsLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("x^1/y"), signalMapper);
        dmsLine->addWidget(b);
        widgetList.append(b);

        // pi, tanh, tan, x^3 and x^1/3
        QHBoxLayout *piLine = new QHBoxLayout;
        cientificLayout->addLayout(piLine);

        b = new Button(QString("pi"), signalMapper);
        piLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("tanh"), signalMapper);
        piLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("tan"), signalMapper);
        piLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("x^3"), signalMapper);
        piLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("x^1/3"), signalMapper);
        piLine->addWidget(b);
        widgetList.append(b);

        // F-E, Exp, Mod, log and 10^x
        QHBoxLayout *feLine = new QHBoxLayout;
        cientificLayout->addLayout(feLine);

        b = new Button(QString("F-E"), signalMapper);
        feLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("Exp"), signalMapper);
        feLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("Mod"), signalMapper);
        feLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("log"), signalMapper);
        feLine->addWidget(b);
        widgetList.append(b);
        b = new Button(QString("10^x"), signalMapper);
        feLine->addWidget(b);
        widgetList.append(b);

        setMinimumSize(sizeHint());
        setMaximumSize(sizeHint());

    }
    /*
    ########################################################################
      Termina a instanciação dos botões da calculadora científica
    ########################################################################
    */

}

// Método que remove os botões da calculadora científica voltando ao modo simples
void CalcGui::changeToSimple() {
    menuShow->hide();
    if (cientific) {
        cientific = false;
        while (widgetList.size()>0) {
            delete widgetList.last();
            widgetList.removeLast();
        }
    }
    setMinimumWidth(sizeHint().rwidth()/2);
    setMaximumWidth(sizeHint().rwidth()/2);
    setMinimumWidth(sizeHint().rwidth()/2);
    setMaximumWidth(sizeHint().rwidth()/2);
}

// Método que mostra uma pequena caixa de diálogo com informções sobre os alunos desenvolvedores da calculadora
void CalcGui::about() {
    QMessageBox *mb = new QMessageBox((QMessageBox::Icon) NULL ,QString(tr("About")),QString(tr("Desenvolvido por Caio e Breno")));
    mb->show();
}
